package tr.gov.tubitak.bilgem.esya.certviewer.viwerasn;

import sun.security.x509.AuthorityKeyIdentifierExtension;
import sun.security.x509.SubjectKeyIdentifierExtension;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import tr.gov.tubitak.bilgem.esya.certviewer.Bundle;
import tr.gov.tubitak.bilgem.esya.certviewer.EByteTools;
import tr.gov.tubitak.bilgem.esya.certviewer.ECertUtil;
import tr.gov.tubitak.bilgem.esya.certviewer.EStringUtils;

import java.io.IOException;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: ramazan.girgin
 * Date: 01.12.2011
 * Time: 11:08
 * To change this template use File | Settings | File Templates.
 */
public class ECertViewerCertificate {
    public ECertViewerCertificate(X509Certificate x509Cert) {
        this.x509Cert = x509Cert;
    }

    public X509Certificate getX509Cert() {
        return x509Cert;
    }

    X509Certificate x509Cert;

    public ECertViewerCertificate(byte[] certData) throws Exception {
        x509Cert = ECertUtil.loadX509Certificate(certData);
    }

    public EName getSubject()
    {
        try {
            X500Name subjectName = new X500Name(x509Cert.getSubjectDN().getName());
            return new EName(subjectName);
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return null;
    }

    public EName getIssuer()
    {
        try {
            X500Name subjectName = new X500Name(x509Cert.getIssuerDN().getName());
            return new EName(subjectName);
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return null;
    }

    public String getKeyUsageListTitle()
    {
        String keyUsageTitle="<html>";
        boolean [] keyUsageValue = x509Cert.getKeyUsage();
        EKeyUsage eKeyUsage=new EKeyUsage(keyUsageValue);
        keyUsageTitle+=eKeyUsage.toItemListTitle();
        keyUsageTitle+="</html>";
        return keyUsageTitle;
    }

    public String getValidFromTitle()
    {
        DateFormat dateFormat = DateFormat.getDateTimeInstance();
        return dateFormat.format(x509Cert.getNotBefore());
    }


    public String getValidToTitle()
    {
        DateFormat dateFormat = DateFormat.getDateTimeInstance();
        return dateFormat.format(x509Cert.getNotAfter());
    }

    public List<ECertField> getFieldList()
    {
        List<ECertField> certFieldList = new ArrayList<ECertField>();
        //V1 fields
        //1-Version
        int version = x509Cert.getVersion();
        String versionStr = "v"+version;
        certFieldList.add(new ECertField(Bundle.getString("ECertField.Version"),versionStr,versionStr,ECertField.ECertFieldType.BASIC_V1));
        //2-Serial Number
        byte[] serialNumberBytes = x509Cert.getSerialNumber().toByteArray();
        String serialNumberStr = EByteTools.toHexString(serialNumberBytes," ");
        certFieldList.add(new ECertField(Bundle.getString("ECertField.SerialNumber"),serialNumberStr,serialNumberStr,ECertField.ECertFieldType.BASIC_V1));

        //Subject
        String subject =getSubject().getString();
        certFieldList.add(new ECertField(Bundle.getString("ECertField.Subject"),subject,subject,ECertField.ECertFieldType.BASIC_V1));

        //Issuer
        String issuer = getIssuer().getString();
        certFieldList.add(new ECertField(Bundle.getString("ECertField.Issuer"),issuer,issuer,ECertField.ECertFieldType.BASIC_V1));

        //valid from
        String validFromStr = getValidFromTitle();
        certFieldList.add(new ECertField(Bundle.getString("ECertField.ValidFrom"),validFromStr,validFromStr,ECertField.ECertFieldType.BASIC_V1));


        //valid to
        String validToStr = getValidToTitle();
        certFieldList.add(new ECertField(Bundle.getString("ECertField.ValidTo"),validToStr,validToStr,ECertField.ECertFieldType.BASIC_V1));
        //3-Signature Algorithm
        String sigAlgStr = x509Cert.getSigAlgName();
        certFieldList.add(new ECertField(Bundle.getString("ECertField.SignatureAlgorithm"),sigAlgStr,sigAlgStr,ECertField.ECertFieldType.BASIC_V1));

        //4-Signature Hash Algorithm
        //<TODO> Signature hash alg nasıl alınacak?

        //5-Public key
        PublicKey publicKey = x509Cert.getPublicKey();
        if(publicKey != null)
        {
            String publicKeyShortStr =publicKey.getAlgorithm();
            String publicKeyLongStr = "";
            if (publicKey instanceof RSAPublicKey)
            {
                RSAPublicKey publicKeyRSA = (RSAPublicKey) publicKey;
                publicKeyShortStr = publicKeyRSA.getAlgorithm()+"("+publicKeyRSA.getModulus().bitLength()+") "+Bundle.getString("ECertViever.Bits");
            }
            else if(publicKey instanceof DSAPublicKey)
            {
                DSAPublicKey publicKeyDSA = (DSAPublicKey) publicKey;
                publicKeyShortStr = publicKeyDSA.getAlgorithm()+"("+publicKeyDSA.getY().bitLength()+") "+Bundle.getString("ECertViever.Bits");
            }

            byte[] publicKeyEncoded = publicKey.getEncoded();
            publicKeyLongStr = EByteTools.toHexString(publicKeyEncoded," ");

            certFieldList.add(new ECertField(Bundle.getString("ECertField.PublicKey"),publicKeyShortStr,publicKeyLongStr, ECertField.ECertFieldType.BASIC_V1));
        }

        //Extensionları'ları yazdırıyoruz
        List<ECertExtension> certExtensions = ECertExtensionFactory.getInstance().getCertExtensions(x509Cert);
        for (ECertExtension certExtension : certExtensions) {
            ECertField.ECertFieldType fieldType= ECertField.ECertFieldType.EXTENSION;
            if(certExtension.isCritical())
            {
                fieldType = ECertField.ECertFieldType.CRITICAL_EXTENSION;
            }
            certFieldList.add(new ECertField(certExtension.getName(),certExtension.getShortTitle(),certExtension.getLongTitle(),fieldType));
        }
        return certFieldList;
    }

    public boolean isQualifiedCertficate(){
        boolean retIsQualified = false;
        String qcStatement = "1.3.6.1.5.5.7.1.3";
        byte[] extensionValue = x509Cert.getExtensionValue(qcStatement);
        if(extensionValue!=null)
        {
            retIsQualified = true;
        }
        return retIsQualified;
    }
}
